home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
p063b9s.zip
/
UNIT
/
LIST.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-03-02
|
41KB
|
1,243 lines
UNIT List;
{╔══════════════════════════════════════════════════════════════════════════╗}
{║ BBS Filelist generator Last changed: 02.03.97 SA ║}
{║ ║}
{║ (C) Copyright 1989-97 by ║}
{║ Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager ║}
{║ ║}
{║ This source may not be given to anybody, without the written permission ║}
{║ from The Portal Team. ║}
{╚══════════════════════════════════════════════════════════════════════════╝}
{$I POPDEFS.Inc}
INTERFACE
USES Use32;
PROCEDURE ListMain;
IMPLEMENTATION
USES Dos, OpDos, OpString, OpDate, OpRoot, OpWindow,
Globals, Areamisc, Util, StrUtil, FileUtil, LogFile, OproUtil,
Nodelist, PoPTypes,NetFile, OpLarray
{$IFDEF MSGOBJECT}
,MKFile, MKMsgAbs, MkObject, MKGlobT
{$ENDIF}
;
PROCEDURE ListMain;
const
topmax = 50;
MaxDupes = 30000;
TYPE
TDupeRec = RECORD
FileName : S12;
Area : S9;
Size : LongInt;
Dupet : Boolean;
END;
TOkCheckRec = RECORD
NodeStat : Byte;
FilePath : StringPtr;
KeyLevelPwd : Boolean;
END;
TOkCheckType = Array[0..MaxAreas] of TOkCheckRec;
TopFilesRec = RECORD
Name : S60;
Times : Word;
Area : Word;
END;
TopFilesType = Array[1..TopMax] of TopFilesRec;
StatistikRec=Record
Files : Word;
Bytes : LongInt;
Pos : LongInt;
END;
StatistikType= Array[1..MaxAreas] of StatistikRec;
AreaFreqLevelType=Array[0..MaxAreas] of Byte;
VAR
OkCheckFile : ^TOkCheckType;
Statistik : ^StatistikType;
BufSiz : Word;
i,a,b : Integer;
ReturnCode : Integer;
Tbdir : FilesRec;
FILES : ^FilesTab;
FilesBBS : ^FilesBBStab;
NumFiles,
NumfilesBBS : Word;
dt : DateTime;
FileAge : Date;
F_List : PBufTextFile; (* Fillisten som den skal se ud *)
F_News : PBufTextFile; (* NewsList - komplet *)
F_OkBim : PBufTextFile; (* Bimodem ok-FILE *)
F_TMP : PBufTextFile; (* DIVERSE *)
F_File : FILE; (* FILE *)
OkFile : TNetFile; (* Portal Ok-FILE *)
NumDupes : Word; (* Indeholder antallet af filer i Dupes *)
Dupes : OpArray;
Dupe : TDupeRec;
TempString : STRING;
DatePicture : STRING[11];
AreaNum : Word;
NewsHeaderAdded : Boolean;
TopFiles : ^TopFilesType;
NewFilesAdded,
CrapFile,
DoDupeCheck,
DupesInLog,
LastWasFile : Boolean;
TotalBytes,
BytesInArea : LongInt;
TotalExisting,
ExistingInArea,
TotalMissing,
MissingInArea,
TotalFiles,
FilesInArea : Integer;
StatStart,
TopStart : Word; {Her starter Statistik og Toplist - FOR seek ved insert}
ListWin1 : WindowPtr;
ListWin2 : WindowPtr;
TmpWin : WindowPtr;
Area : AreaTabPtr;
ViHarSnydt : Boolean;
AreaFreqLevel: ^AreaFreqLevelType;
TmpDate : Date;
FooterStartPos : LongInt;
LABEL
SnydeFidus;
{$IFDEF MSGOBJECT}
Procedure PostStatMsg;
VAR
Msg : AbsMsgPtr;
BEGIN
(*
If OpenMsgArea(Msg, 'SC:\MSG\LOCAL') Then
BEGIN
Msg^.StartNewMsg;
Msg^.SetFrom('PoP-List');
Msg^.SetTo(Cfg.sysop);
Msg^.SetSubj('Statistics');
Msg^.SetPriv(True);
Msg^.SetDate(DateStr(GetDosDate));
Msg^.SetTime(TimeStr(GetDosDate));
Msg^.SetLocal(True);
Msg^.SetOrig(Cfg.Addresses[Cfg.MainAdrNum]);
Msg^.SetDest(Cfg.Addresses[Cfg.MainAdrNum]);
Msg^.DoStringLn('');
Msg^.DoStringLn('PoP-List statistics:');
Msg^.DoStringLn('');
Msg^.DoStringLn('Total Files :'+LONGINTFORM('#,###,###',TotalFiles));
Msg^.DoStringLn('Total Existing:'+LONGINTFORM('#,###,###',TotalExisting));
Msg^.DoStringLn('Total Missing :'+LONGINTFORM('#,###,###',TotalMissing));
Msg^.DoStringLn('Total KBytes :'+LONGINTFORM('#,###,###',TotalBytes));
Msg^.DoStringLn('');
Msg^.DoStringLn('--- PoP-List v'+ver);
Msg^.DoStringLn(' * Origin: Now you are playing with Power... Portal of Power! (0:0/0.0)');
Msg^.WriteMsg;
CloseMsgArea(Msg);
END;
*)
END;
{$ENDIF}
PROCEDURE UpdateScreen;
BEGIN
ListWin2^.wFasttext('Area no. : '+Pad(Trim(Area^[i]^.Tag^),10),2,2);
ListWin2^.wFasttext('Area desc. : '+Pad(Copy(Area^[i]^.Title^,1,45),45),3,2);
ListWin2^.wFasttext(LONGINTFORM(' #,###,###,###',FilesInArea)+LONGINTFORM(' #,###,###,###',ExistingInArea)+
LONGINTFORM(' #,###,###,###',missingInArea)+LONGINTFORM(' #,###,###,###',(BytesInArea DIV 1024)),6,17);
ListWin2^.wFasttext(LONGINTFORM(' #,###,###,###',TotalFiles)+LONGINTFORM(' #,###,###,###',TotalExisting)+
LONGINTFORM(' #,###,###,###',Totalmissing)+LONGINTFORM(' #,###,###,###',TotalBytes),7,17);
END;
PROCEDURE ShowScreen(OnOff:Boolean);
BEGIN
IF OnOff THEN
BEGIN
MyWin(ListWin1,25,2,55,9,2,'PoP-List current function',False);
MyWin(ListWin2,1,12,80,23,2,'PoP-List status display',False);
ListWin2^.wFasttext(' Total Existing Missing KBytes',5,1);
ListWin2^.wFasttext('Current area:',6,2);
ListWin2^.wFasttext('All areas :',7,2);
ListWin1^.wFastText('Reading FileAreas',1,6);
ListWin1^.wFastText('Reading FILES.BBS',2,6);
ListWin1^.wFastText('Processing FILES.BBS',3,6);
ListWin1^.wFastText('Writing filelists',4,6);
ListWin1^.wFastText('Looking for dupes',5,6);
ListWin1^.wFastText('Cleaning up',6,6);
END ELSE
BEGIN
KillWindow(ListWin2);
KillWindow(ListWin1);
END;
END;
PROCEDURE Arrow(yy:byte);
Var
zy : Byte;
BEGIN
FOR zy:=1 TO 6 DO
IF zy=yy THEN
ListWin1^.wFastText('══',zy,2)
Else
ListWin1^.wFastText(' ',zy,2);
END;
FUNCTION IncludeArea(CONST Tag:S20):BOOLEAN;
VAR
y:BYTE;
s:S20;
BEGIN
IncludeArea:=True;
s:=StUpCase(Trim(Tag));
FOR y:= 1 TO 11 DO
IF s=StUpCase(Trim(Cfg.ListFiles.PrivateAreas[y])) THEN
BEGIN
IncludeArea:=False;
Break;
END;
END;
PROCEDURE AddFile(F1, F2: PBufTextFile);
VAR
s : STRING;
BEGIN
WHILE NOT F1^.Eof DO
BEGIN
F1^.ReadLn(S);
F2^.WriteLn(S);
END;
END;
PROCEDURE CheckPortalOkFile;
VAR
OkFileRec:TOkFile;
x,
Count : Word;
FUNCTION ExistInPopOk(CONST S: STRING):Boolean;
VAR
Found:Boolean;
i : Word;
BEGIN
Found:=False;
FOR i:=1 TO Count DO
BEGIN
IF (StUpCase(AddBackSlash(JustPathName(OkCheckFile^[i].FilePath^)))=AddBackSlash(StUpCase(s))) THEN
BEGIN
Found:=True;
IF (OkCheckFile^[i].KeyLevelPwd) THEN
AreaFreqLevel^[x]:=OkCheckFile^[i].NodeStat
ELSE
AreaFreqLevel^[x]:=0;
Break;
END;
END;
ExistInPopOk:=Found;
END;
PROCEDURE OpenOkFile;
BEGIN
OkFile.Open(StartPath+PoPOkFileName,SizeOf(TOkFile),True);
END;
BEGIN
FillChar(AreaFreqLevel^,SizeOf(AreaFreqLevelType),255);
New(OkCheckFile);
OpenOkFile;
Count:=0;
WHILE NOT OkFile.Eof DO
BEGIN
OkFile.Read(OkFileRec,NoKeep,Wait) ;
IF (TrimSpaces(OkFileRec.MagicName)='') THEN
BEGIN
Inc(Count);
OkCheckFile^[Count].NodeStat:=BYTE(OkFileRec.NodeStat)+1;
OkCheckFile^[Count].FilePath:=StringToHeap(StUpCase(AddBackSlash(JustPathName(OkFileRec.FilePath))));
IF (OkFileRec.Level+OkFileRec.Keys = 0) AND (TrimSpaces(OkFileRec.PassWord)='') THEN
OkCheckFile^[Count].KeyLevelPwd:=True
ELSE
OkCheckFile^[Count].KeyLevelPwd:=False;
END;
END;
FOR x:=1 TO AreaNum DO
BEGIN
IF IncludeArea(Area^[x]^.Tag^) THEN
BEGIN
IF NOT ExistInPopOk(Area^[x]^.Path^) THEN
BEGIN
IF Cfg.ListFiles.OkPortal THEN
BEGIN
AddLog('*','Adding '+Area^[x]^.path^+' To Portal OK-File');
FillChar(OkFileRec,SizeOf(OkFileRec),0);
OkFileRec.FilePath:=StUpCase(Addbackslash(Area^[x]^.Path^)+'*.*');
OkFile.PutRec(OkFileRec, OkFile.FileSize);
AreaFreqLevel^[x]:=1;
END;
END;
END;
END;
FOR x:=1 TO Count DO
DisposeString(OkCheckFile^[x].FilePath);
Dispose(OkCheckFile);
OkFile.Close;
END;
PROCEDURE POPfooter(f: PBufTextFile; Totals: Boolean);
BEGIN
f^.WriteLn('');
f^.WriteLn('');
IF Totals THEN
BEGIN
f^.WriteLn(center('Totals for all areas: '+Trimspaces(LongintForm('#####',TotalExisting))+' files, Using '
+Trimspaces(LongIntForm('#,###',(Totalbytes div 1024)))+' Mb.',79));
f^.WriteLn('');
END;
f^.WriteLn('╒════════════════╡ Last updated: '+TodayString('dd-nnn-yyyy')+' at '+
CurrentTimeString('hh:mm:ss')+' ╞════════════════╕');
f^.WriteLn('│'+center('PoP-List v'+ver+' - a part of the Portal Of Power Mailer',76)+'│');
f^.WriteLn('├'+CharStr('─',76)+'┤');
f^.WriteLn('│ (C) Copyright 1989-97 by The Portal Team │');
f^.WriteLn('│ All Rights Reserved. │');
f^.WriteLn('╘'+CharStr('═',76)+'╛');
END;
PROCEDURE HeaderText(f: PBufTextFile);
BEGIN
f^.WriteLn('╞════════════╤═══════╤═════════╤═════════════════════════════════════════════╡');
f^.WriteLn('│ Filename │ Bytes │ Date │ File-description │');
f^.WriteLn('╘════════════╧═══════╧═════════╧═════════════════════════════════════════════╛');
END;
PROCEDURE WriteHeader(I:Word);
BEGIN
F_List^.WriteLn('');
F_List^.WriteLn('');
F_List^.WriteLn('');
F_List^.WriteLn('╒'+CharStr('═',76)+'╕');
F_List^.WriteLn('│'+center('('+Trim(Area^[i]^.tag^)+') '+Copy(Area^[i]^.Title^,1,76),76)+'│');
F_List^.WriteLn('├'+CharStr('─',76)+'┤');
F_List^.WriteLn('│ Bytes On-line: '+LongIntForm('###.###.###',BytesInArea)+' Files On-line: '+
LongIntForm('#.###',ExistingInArea)+' Files Off-line:'+LongIntForm('#.###',MissingInArea)+' │');
HeaderText(F_List);
IF AreaFreqLevel^[i]<255 THEN
F_List^.WriteLn(center(Cfg.ListFiles.TXTFreq[AreaFreqLevel^[i]],78))
ELSE
F_List^.WriteLn('');
F_List^.WriteLn('');
END;
PROCEDURE WriteNewsHeader;
BEGIN
IF F_News<>NIL THEN
BEGIN
F_News^.WriteLn('');
F_News^.WriteLn('');
F_News^.WriteLn('╒'+CharStr('═',76)+'╕');
F_News^.WriteLn('│'+center('('+Trim(Area^[i]^.tag^)+') '+Copy(Area^[i]^.Title^,1,76),76)+'│');
HeaderText(F_News);
F_News^.WriteLn('');
END;
END;
PROCEDURE Top(CONST Filest: STRING; Areano: Integer);
VAR
z : Byte;
BEGIN
a:=GetDlC(FileSt);
IF (a > TopFiles^[Cfg.ListFiles.top].Times) AND (a>0) THEN
BEGIN
b:=Cfg.ListFiles.Top;
FOR z:=Cfg.ListFiles.Top downto 1 DO
IF a > TopFiles^[z].Times THEN b:=z;
IF B<>Cfg.ListFiles.Top THEN Move(TopFiles^[b],TopFiles^[b+1],SizeOf(TopFilesRec)*(Cfg.ListFiles.Top-b-1));
TopFiles^[b].Name:=Filest;
TopFiles^[b].Times:= a;
TopFiles^[b].Area:=areano;
END;
END;
FUNCTION FindInDir(FileName: S12; Var Dinfo: FilesRec) : Integer;
VAR
top,bund,test : Integer;
BEGIN
top:=NumFiles;
bund:=1;
FileName:=StUpCase(Copy(FileName,1,pos(' ',FileName+' ')-1));
IF FileName<>'' THEN
BEGIN
REPEAT
test:=(top+bund) DIV 2;
IF Files^[test].Name>FileName THEN
top:=test-1
ELSE
IF Files^[test].Name<FileName THEN bund:=test+1;
UNTIL (top<=bund) OR (FileName=Files^[test].Name);
test:=(top+bund) DIV 2;
Dinfo:=Files^[Test];
IF Files^[test].Name<>FileName THEN test:=0;
END ELSE
test:=0;
FindInDir:=test;
END;
PROCEDURE CalcStat;
VAR
ZZ : Word;
BEGIN
FOR zz:=1 TO NumFilesBBS DO
BEGIN
TempString:=FilesBBS^[zz]^.Tekst^;
IF HasFileName(TempString) THEN
BEGIN
Inc(FilesInArea);
IF FindInDir(TrimSpaces(Copy(TempString,1,12)), TbDir)<>0 THEN
BEGIN
Inc(ExistingInArea);
BytesInArea:=BytesInArea+TbDir.Size;
END ELSE
Inc(MissingInArea);
END;
END;
Statistik^[i].Files:=ExistingInArea;
Statistik^[i].Bytes:=BytesInArea;
Statistik^[i].Pos:=F_List^.Getpos;
END;
FUNCTION SortDupeFile: Boolean;
VAR
Escaped : Boolean;
PROCEDURE QuickSort(L, R : Word);
{-Non-recursive QuickSort per N. Wirth's "Algorithms AND Data Structures"}
const
StackSize = 20;
type
Stack = array[1..StackSize] of Word;
var
Lstack : Stack; {Pending partitions, left edge}
Rstack : Stack; {Pending partitions, right edge}
StackP : Integer; {Stack Pointer}
Pl : Word; {Left edge within partition}
Pr : Word; {Right edge within partition}
StrPl, StrPr, Pivot : TDupeRec;
BEGIN
{$IFDEF LISTDEBUG}
Addlog(' ','DEBUG : STARTING FileSort');
Addlog(' ','DEBUG : MEMAVAIL:'+LongIntForm('#######',MemAvail));
Addlog(' ','DEBUG : MAXAVAIL:'+LongIntForm('#######',MaxAvail));
{$ENDIF}
{Initialize the stack}
StackP:=1;
Lstack[1]:=L;
Rstack[1]:=R;
Write('>>');
{Repeatedly take top partition from stack}
repeat
{Pop the stack}
L:=Lstack[StackP];
R:=Rstack[StackP];
Dec(StackP);
Write(#8'<'#8);
{Sort current partition}
repeat
{Load the pivot element}
Dupes.RetA(L+Random(R-L), 0, Pivot);
Pl:=L;
Pr:=R;
{Swap items in sort order around the pivot index}
repeat
Dupes.RetA(Pl, 0, StrPl);
WHILE StrPl.FileName<Pivot.FileName DO
BEGIN
Inc(Pl);
Dupes.RetA(Pl, 0, StrPl);
END;
Dupes.RetA(Pr, 0, StrPr);
WHILE StrPr.FileName>Pivot.FileName DO
BEGIN
Dec(Pr);
Dupes.RetA(Pr, 0, StrPr);
END;
IF Pl <= Pr THEN
BEGIN
IF Pl <> Pr THEN
BEGIN
{Swap the two elements}
Dupes.SetA(Pl, 0, StrPr);
Dupes.SetA(Pr, 0, StrPl);
{ Tmp:=SortPointer(Pl);
SetPointer(SortPointer(Pr), Pl);
SetPointer(Tmp, Pr); }
END;
IF Pl < 65535 THEN Inc(Pl);
IF Pr > 0 THEN Dec(Pr);
END;
Escaped:=GotEsc;
IF Escaped THEN Exit;
until Pl > Pr;
{Decide which partition TO sort next}
IF (Pr-L) < (R-Pl) THEN
BEGIN
{Left partition is bigger}
IF Pl < R THEN
BEGIN
{Stack the request FOR sorting right partition}
Inc(StackP);
Lstack[StackP]:=Pl;
Rstack[StackP]:=R;
Write('>');
END;
{Continue sorting left partition}
R:=Pr;
END else
BEGIN
{Right partition is bigger}
IF L < Pr THEN
BEGIN
{Stack the request FOR sorting left partition}
Inc(StackP);
Lstack[StackP]:=L;
Rstack[StackP]:=Pr;
Write('>');
END;
{Continue sorting right partition}
L:=Pl;
END;
until L >= R;
until StackP <= 0;
Write(#8'<'#8);
{$IFDEF LISTDEBUG}
Addlog(' ','DEBUG : Ending FileSort');
{$ENDIF}
END;
BEGIN
Escaped:=False;
Dec(NumDupes);
QuickSort(0,NumDupes);
SortDupeFile:=NOT Escaped;
END;
FUNCTION SizeCheck(a,b:LongInt):Boolean; {Returns True IF less than Threshold}
VAR
c : longint;
BEGIN
IF (a=b) or (a=0) THEN
BEGIN
SizeCheck:=True;
Exit;
END;
c:=ABS(a-b);
SizeCheck:=((c*100) div a) < Cfg.ListFiles.Threshold;
END;
PROCEDURE CheckDupeFile;
Var
ff: PBufTextFile;
n1,n2,
n,
FirstDupe,
LastDupe : Word;
Dupe1,
Dupe2 : TDupeRec;
BEGIN
Addlog('#','Loking for dupes');
{$IFDEF LISTDEBUG}
Addlog(' ','DEBUG : STARTING DupeCheck');
{$ENDIF}
MyWin(TmpWin,15,9,65,11,2,'Dupe check in progress',False);
IF SortDupeFile THEN;
FirstDupe:=65535;
LastDupe:=0;
IF TrimSpaces(Cfg.ListFiles.DupeReport)='' THEN DupesInLog:=True Else DupesInLog:=False;
IF NOT DupesInLog THEN
BEGIN
New(ff, Init(Cfg.Listfiles.DupeReport, SCreate, 1024));
IF ff<>NIL THEN
BEGIN
ff^.WriteLn('╒'+CharStr('═',76)+'╕');
ff^.WriteLn('│'+Center('Dupe report',76)+'│');
ff^.WriteLn('╘'+CharStr('═',76)+'╛');
ff^.WriteLn('');
END ELSE
DupesInLog:=True;
END;
{$IFDEF LISTDEBUG}
Addlog(' ','DEBUG : Beginning to compare sorted files');
{$ENDIF}
FOR n:=0 TO NumDupes-1 DO
BEGIN
Dupes.RetA(n,0,Dupe1);
Dupes.RetA(n+1,0,Dupe2); {Originalen}
IF JustName(Dupe1.FileName)=JustName(Dupe2.FileName) THEN
BEGIN
IF FirstDupe=65535 THEN FirstDupe:=N;
END ELSE
BEGIN
IF FirstDupe<>65535 THEN
BEGIN
FOR n1:= FirstDupe TO N-1 DO
BEGIN
{ FOR n2:= FirstDupe+1 TO n DO }
FOR n2:= n1+1 TO n DO
BEGIN
Dupes.RetA(n1,0,Dupe1);
Dupes.RetA(n2,0,Dupe2);
IF SizeCheck(Dupe1.Size,Dupe2.Size) THEN
BEGIN {WriteToLog AND Set .Dupet=True}
IF DupesInLog THEN
BEGIN
IF NOT Dupe1.Dupet THEN AddLog('*','Dupe: '+Dupe1.FileName+' ('
+Longintform('##.###',(Dupe1.Size DIV 1024))+'K) in area: '+Dupe1.Area);
IF NOT Dupe2.Dupet THEN AddLog('*','Dupe: '+Dupe2.FileName+' ('
+Longintform('##.###',(Dupe2.Size DIV 1024))+'K) in area: '+Dupe2.Area);
END ELSE
BEGIN
IF NOT Dupe1.Dupet THEN ff^.WriteLn(Dupe1.FileName+' ('
+Longintform('##.###',(Dupe1.Size DIV 1024))+'K) in area: '+Dupe1.Area);
IF NOT Dupe2.Dupet THEN ff^.WriteLn(Dupe2.FileName+' ('
+Longintform('##.###',(Dupe2.Size DIV 1024))+'K) in area: '+Dupe2.Area);
END;
Dupe1.Dupet:=True;
Dupe2.Dupet:=True;
Dupes.SetA(n1,0,Dupe1);
Dupes.SetA(n2,0,Dupe2);
END;
END;
END;
FirstDupe:=65535;
END;
END;
END;
IF NOT DupesInLog THEN
BEGIN
POPFooter(ff,False);
Dispose(ff, Done);
END;
{$IFDEF LISTDEBUG}
Addlog(' ','DEBUG : Finished Comparing sorted files');
{$ENDIF}
KillWindow(TmpWin);
END;
PROCEDURE ProcessFilesBBS(Nummer:Integer);
Var
ANumber,
TmpWord,
zz : Word;
F_Touch : FILE;
PROCEDURE WriteLine(F: PBufTextFile);
VAR
Tmp,OutStr, Overlap : STRING;
i : Byte;
BEGIN
Tmp:=TrimLead(Copy(Tempstring,13,Length(TempString)-12));
IF (Cfg.BBS.BBSType=btMax) AND (Length(Tmp)>0) AND (Tmp[1]='/') THEN
BEGIN
i:=Pos(' ',Tmp);
IF i>0 THEN Delete(Tmp,1,i) ELSE Tmp:='';
END;
IF (Cfg.AreaMan.InsDlCnt) AND (Cfg.AreaMan.DlCDigits<>0) THEN i:=Cfg.AreaMan.DlCDigits+3 ELSE i:=0;
WordWrap(Tmp,OutStr,Overlap,46,False);
f^.WriteLn(Form(' ####### ',TbDir.Size)+DMYtoDateString(DatePicture,Dt.day,Dt.Month,Dt.Year)+' '+OutStr);
WHILE Overlap<>'' DO
BEGIN
WordWrap(Overlap,OutStr,Overlap,46-i,False);
f^.WriteLn(CharStr(' ',33+i)+OutStr);
END
END;
function CheckCrapfiles(CONST s: STRING):boolean;
VAR
I : Byte;
HaveChar : Boolean;
BEGIN
I:=1;
HaveChar:=False;
WHILE (i<= Length(s)) AND NOT havechar DO
BEGIN
HaveChar:=NOT(s[i] In ['?','*','.']);
Inc(i);
END;
CheckCrapFiles:=HaveChar;
END;
PROCEDURE DeleteCrap;
Var
z : Byte;
DirInfo: SearchRec; { FOR Windows, use TSearchRec }
BEGIN
FOR z:=1 TO 10 DO
IF CheckCrapFiles(Cfg.ListFiles.CrapFiles[z]) THEN
BEGIN { FOR Windows, use faArchive }
FindFirst(Cfg.ListFiles.CrapFiles[z], Archive, DirInfo); { Same as DIR *.PAS }
WHILE DosError = 0 DO
BEGIN
IF DeleteFile(DirInfo.Name) THEN
AddLog('*', Pad(DirInfo.Name,12)+' in area '+Trim(Area^[Nummer]^.Tag^)+' deleted');
FindNext(DirInfo);
END;
FindClose(DirInfo);
END;
END;
BEGIN
Arrow(2);
NumFilesBBS:=0;
FilesInArea:=0;
ExistingInArea:=0;
MissingInArea:=0;
BytesInArea:=0;
IF ChangeDir(Area^[Nummer]^.path^) THEN
BEGIN
IF NOT Str2Word(AREA^[Nummer]^.Tag^,ANumber) THEN ANumber:=0;
IF ReadFilesInArea(AREA^[Nummer]^.Fpath^,6,Files^,FilesBBS^,NumFilesBBS,NumFiles,ANumber) THEN
BEGIN
DeleteCrap;
IF Cfg.ListFiles.Adopt THEN
BEGIN
IF AdoptOrphans(True,False,FilesBBS^,Files^,NumFiles,NumFilesBBS,Cfg.ListFiles.AdoptComment) THEN
BEGIN
WriteCurrentFilesBBS(Area^[Nummer]^.Fpath^,NumFilesBBS,FilesBBS^,FALSE);
END;
END;
{-- FreqOk:=UpDatePopOkFile(Area^[Nummer]^.path,Cfg.ListFiles.OkPortal); }
ChangeDir(StartPath);
Arrow(3);
CalcStat;
Inc(TotalFiles,FilesInArea);
Inc(TotalExisting,ExistingInArea);
TotalBytes:=TotalBytes+(BytesInArea DIV 1024);
Inc(TotalMissing,MissingInArea);
WriteHeader(Nummer);
NewsHeaderAdded:=False;
NewFilesAdded:=False;
CrapFile:=False;
LastWasFile:=False;
FOR ZZ:=1 TO NumFilesBBS DO
BEGIN
TempString:=FilesBBS^[zz]^.Tekst^;
IF Cfg.AreaMan.InsDlCnt THEN AddDlc(TempString);
IF ((HasFileName(TempString)) AND (NOT CrapFile)) THEN
BEGIN
LastWasFile:=True;
IF Cfg.ListFiles.Top <> 0 THEN top(TempString,i); {I er stadig areanummeret}
F_List^.WriteNoLn(CPad(TempString,12));
ReturnCode:=FindInDir(TrimSpaces(Copy(TempString,1,12)),TbDir);
IF ReturnCode<>0 THEN
BEGIN
IF DoDupeCheck THEN {Add2DupeFile(StUpCase(Copy(Pad(TempString,12),1,12)),AREA^[Nummer]^.Tag);}
BEGIN
Dupe.FileName:=StUpCase(CPad(TempString,12));
Dupe.Area:=AREA^[Nummer]^.Tag^;
Dupe.Size:=TbDir.size;
Dupe.Dupet:=False;
Dupes.SetA(NumDupes,0,Dupe);
Inc(NumDupes);
END;
UnpackTime(TbDir.Time,dt);
TmpDate:=DMYtoDate(Dt.Day,Dt.Month,Dt.Year);
IF (Cfg.ListFiles.Touch) AND (Today > 143540) THEN {KUN Hvis TODAY>1992}
IF (TmpDate > Today) or (TmpDate<139523) THEN {Hvis >today or <01-01-82}
BEGIN
GetDate(Dt.Year,Dt.Month,Dt.Day,TmpWord);
GetTime(Dt.Hour,Dt.Min,Dt.Sec,TmpWord);
PackTime(Dt,TbDir.Time);
TmpDate:=Today;
Assign(F_Touch,AddBackSlash(Area^[Nummer]^.path^)+TbDir.Name); FileMode:=ShareRead+ShareDenyNone;
Reset(F_Touch);
IF IOResult=0 THEN
BEGIN
SetFTime(F_Touch,TbDir.time);
Close(F_Touch);
END;
AddLog('*','Touched '+TbDir.Name+' in area: '+Trim(AREA^[Nummer]^.Tag^));
END;
FileAge:=Today-TmpDate;
IF (FileAge<Cfg.ListFiles.NewsDays) AND (Fileage>=0) THEN
BEGIN
IF NOT NewsHeaderAdded THEN
BEGIN
NewsHeaderAdded:=True;
WriteNewsHeader;
END;
NewFilesAdded:=True;
IF F_News<>NIL THEN
BEGIN
F_News^.WriteNoLn(CPad(TempString,12));
WriteLine(F_News);
END;
END;
WriteLine(F_List);
END Else
BEGIN
IF NOT CrapFile THEN
BEGIN
F_List^.WriteLn(' Offline N/A '+Copy(Tempstring,13,255));
END;
END;
END else
IF NOT CrapFile THEN
BEGIN
IF (LastWasFile AND (TrimSpaces(TempString)<>'') ) THEN
BEGIN
F_List^.WriteLn(CharStr(' ',33)+trimspaces(TempString));
END else
BEGIN
F_List^.WriteLn(TempString);
LastWasFile:=False;
END;
END;
END;
END;
DeallocateFiles(FilesBBS^,NumFilesBBS);
ChangeDir(StartPath);
END ELSE
CalcStat;
END;
PROCEDURE IWriteLn(VAR F: FILE; CONST S: STRING);
Var
Result : Word;
ss : STRING;
BEGIN
ss:=CPad(s,79)+#13+#10;
BlockWrite(F,SS[1],81,Result);
END;
PROCEDURE WriteFooter(F: PBufTextFile);
BEGIN
f^.WriteLn('');
f^.WriteLn('╒'+CharStr('═',76)+'╕');
f^.WriteLn('│ PoP-List - Portal Of Power - (C) 1989-97 by The Portal Team │');
f^.WriteLn('╘'+CharStr('═',76)+'╛');
END;
PROCEDURE InsertStat(CONST FName: PathStr; Start: LongInt);
VAR
f : FILE;
FT : PBufTextFile;
s : STRING;
x : Word;
Len : Byte;
BEGIN
IF Cfg.BBS.BBSType=btMax THEN Len:=9 ELSE Len:=3;
IF Cfg.ListFiles.Stat THEN
BEGIN
Assign(F,fName);FileMode:=ShareWrite+ShareDenyW;
Reset(F,1);
IF IOResult <> 0 THEN
BEGIN
AddLog('!','Error inserting Statistic-file - Ignoring!');
Exit;
END;
Seek(F,Start);
IWriteLn(F,'┌'+CharStr('─',75)+'┐');
IWriteLn(F,'│ '+Pad('Area',Len+3)+Pad('Title',52-Len)+'Files KBytes │');
IWriteLn(F,'└'+CharStr('─',75)+'┘');
END;
IF Cfg.ListFiles.StatFile <>'' THEN
BEGIN
New(FT, Init(Cfg.ListFiles.StatFile, SCreate, Max64k(MaxAvail-1024)));
IF FT=NIL THEN
BEGIN
AddLog('!','Error writing Statistic-file - Ignoring!');
Exit;
END;
FT^.WriteLn('┌'+CharStr('─',75)+'┐');
FT^.WriteLn('│ '+Pad('Area',Len+3)+Pad('Title',52-Len)+'Files KBytes │');
FT^.WriteLn('└'+CharStr('─',75)+'┘');
END ELSE
FT:=NIL;
FOR x:=1 TO AreaNum DO
BEGIN
IF IncludeArea(Area^[x]^.Tag^) THEN
BEGIN
S:=' '+CPad(Trim(Area^[x]^.tag^),Len)+' '+CPad(Area^[x]^.Title^,52-Len)+
LONGINTFORM('#.###',Statistik^[x].Files)+ LongIntForm(' ###.###.###',(Statistik^[x].Bytes DIV 1024));
IF Cfg.ListFiles.Stat THEN IWriteLn(F,s);
IF FT<>NIL THEN FT^.WriteLn(s);
END;
END;
IF Cfg.ListFiles.Stat THEN
BEGIN
IWriteLn(F,CharStr('─',77));
IWriteLn(F,CharStr(' ',Len+5)+Pad('Total for all file-areas',50-Len)+
LongIntForm('###.###',TotalExisting)+ LongIntForm(' ###.###.###',TotalBytes));
Close(F);
END;
IF FT<>NIL THEN
BEGIN
FT^.WriteLn(CharStr('─',77));
FT^.WriteLn(CharStr(' ',Len+5)+Pad('Total for all file-areas',50-Len)+
LongIntForm('###.###',TotalExisting)+ LongIntForm(' ###.###.###',TotalBytes));
WriteFooter(FT);
Dispose(FT, Done);
END;
END;
PROCEDURE InsertTop(CONST FName: PathStr; Start: LongInt);
VAR
x : Integer;
f : FILE;
Len : Byte;
BEGIN
IF Cfg.BBS.BBSType=btMax THEN Len:=9 ELSE Len:=3;
Arrow(6);
Assign(F,fName);FileMode:=ShareWrite+ShareDenyW;
Reset(F,1);
IF IOResult=0 THEN
BEGIN
Seek(F,Start);
IWriteLn(F,' TOP-'+TrimSpaces(LongIntForm('##',Cfg.ListFiles.Top))+
' downloaded files:');
IWriteLn(F,CharStr('─',78));
FOR x:= 1 TO Cfg.ListFiles.Top DO
BEGIN
IF (Cfg.BBS.BBSType=btMax) AND (Length(TopFiles^[x].Name)>0) AND (TopFiles^[x].Name[14]='/') THEN
BEGIN
i:=Pos(' ',copy(TopFiles^[x].Name,14,255));
IF i>0 THEN Delete(TopFiles^[x].Name,14,i) ELSE TopFiles^[x].Name:=copy(TopFiles^[x].Name,1,12);
END;
IF topFiles^[x].Area <> 0 THEN
IWriteLn(F,LongIntForm('## ',x)+CPad(TopFiles^[x].Name,63-len)+
' Area: ('+CPad(Trim(Area^[topFiles^[x].Area]^.Tag^), Len)+')');
END;
IWriteLn(F,CharStr('─',78));
Close(F);
END;
END;
PROCEDURE WriteTop;
VAR
F_Top : PBufTextFile;
x : Integer;
Len : Byte;
BEGIN
IF Cfg.BBS.BBSType=btMax THEN Len:=9 ELSE Len:=3;
Arrow(6);
New(F_Top, Init(Cfg.ListFiles.TopFile, SCreate, Max64k(MaxAvail-1024)));
IF F_Top<>NIL THEN
BEGIN
F_Top^.WriteLn(' TOP-'+Long2Str(Cfg.ListFiles.Top)+' downloaded files:');
F_Top^.WriteLn(CharStr('─',78));
FOR x:= 1 TO Cfg.ListFiles.Top DO
BEGIN
IF (Cfg.BBS.BBSType=btMax) AND (Length(TopFiles^[x].Name)>0) AND (TopFiles^[x].Name[14]='/') THEN
BEGIN
i:=Pos(' ',copy(TopFiles^[x].Name,14,255));
IF i>0 THEN Delete(TopFiles^[x].Name,14,i) ELSE TopFiles^[x].Name:=copy(TopFiles^[x].Name,1,12);
END;
IF topFiles^[x].Area <> 0 THEN
F_Top^.WriteLn(LongIntForm('## ',x)+CPad(TopFiles^[x].Name,63-len)+
' Area: ('+CPad(Trim(Area^[topFiles^[x].Area]^.Tag^),len)+')');
END;
F_Top^.WriteLn(CharStr('─',78));
WriteFooter(F_Top);
Dispose(F_Top, Done);
END ELSE
AddLog('!','Error writing TopList - Ignoring!');
END;
Procedure MakeSegments;
Var
F_Segment : PBufTextFile;
s : String;
{ F_MFS : TNetFile;}
FileListSegment : TFileListSegment;
PROCEDURE Add2Segment(Seg1,Seg2:LongInt);
BEGIN
F_LIST^.Seek(Seg1);
While (F_LIST^.GetPos < Seg2) DO
BEGIN
F_LIST^.ReadLn(s);
F_Segment^.WriteLn(s);
END;
END;
Function FindAreaStart(Tag : String):LongInt;
VAR
x : Longint;
FoundVal : LongInt;
BEGIN
FoundVal := 0;
For x := 1 to AreaNum do
BEGIN
If StUpCase(Trim(Area^[x]^.Tag^)) = Tag then
FoundVal := X;
END;
FindAreaStart := FoundVal;
END;
PROCEDURE ProcessSegment;
Var
ss : String;
SWord : String;
WordNum : Byte;
SegStart : LongInt;
SegSlut : LongInt;
BEGIN
New(F_Segment,Init(FileListSegment.FileName,SCreate,Max64K((MaxAvail-2048) DIV 2)));
IF (FileListSegment.HeaderFile<>'') AND (ExistFile(FileListSegment.HeaderFile)) THEN
BEGIN
New(F_Tmp, Init(FileListSegment.HeaderFile, SOpenRead+ShareDenyW, Max64k(MaxAvail-2048)));
IF F_Tmp<>NIL THEN
BEGIN
AddFile(F_Tmp, F_Segment);
Dispose(F_Tmp, Done);
END;
END;
With FileListSegment do
ss:=StUpCase(IncludeAreas[1]+' '+IncludeAreas[2]+' '+IncludeAreas[3]+' '+IncludeAreas[4]);
WordNum:=0;
Repeat
Inc(WordNum);
sWord := ExtractWord(WordNum,ss,[' ']);
If sWord <> '' then
BEGIN
SegStart := FindAreaStart(SWord);
If (SegStart <>0) and (Statistik^[SegStart].Pos<>0) then
BEGIN
If ExtractWord(WordNum+1,ss,[' '])='-' then
BEGIN
Inc(WordNum,2);
sWord := ExtractWord(WordNum,ss,[' ']);
If sWord <> '' then
SegSlut := FindAreaStart(sWord) + 1
ELSE
BEGIN
AddLog('!','MultiList Area not found: '+sWord);
SegSlut := SegStart+1;
END;
END ELSE
SegSlut := SegStart+1;
While (Statistik^[SegSlut].Pos = 0) and (SegSlut<AreaNum) do
Inc(SegSlut);
If SegSlut > AreaNum then
SegSlut := FooterStartPos
ELSE
SegSlut := Statistik^[SegSlut].Pos;
{ AddLog('!','Writing Segment: '+FileListSegment.Name+' :'+LongIntForm('###.###.###',
Statistik^[SegStart].pos)+' -'+LongIntForm('###.###.###',SegSlut)); }
Add2Segment(Statistik^[SegStart].pos,SegSlut);
END ELSE
AddLog('!','MultiList Area Not Found: '+sWord);
END;
UNTIL sWord = '';
PopFooter(F_Segment, False);
Dispose(F_Segment, Done);
END;
BEGIN
Arrow(4);
New(F_LIST,INIT(Cfg.ListFiles.FileList,SOpenRead+ShareDenyW,Max64K((MaxAvail-2048) DIV 3)));
IF F_LIST<>NIL THEN
BEGIN
OkFile.Open(StartPath+PoPListSegmentsName,SizeOf(TFileListSegment),True);
While Not OkFile.EOF do
BEGIN
OkFile.Read(FileListSegment, NoKeep,Wait) ;
AddLog('*', 'MultiList Segment: '+FileListSegment.Name);
ProcessSegment;
IF FileListSegment.Doafter<>'' THEN RunCmd(FileListSegment.DoAfter,JustPathname(FileListSegment.FileName));
END;
{ F_MFS.Close;}
Dispose(F_List, Done);
END;
END;
BEGIN
{$IFNDEF PoPLite}
FreeUpMemory;
ShowScreen(True);
Arrow(1);
TotalFiles:=0;
TotalMissing:=0;
TotalExisting:=0;
TotalBytes:=0;
FilesInArea:=0;
MissingInArea:=0;
ExistingInArea:=0;
BytesInArea:=0;
NumDupes:=0;
ViHarSnydt:=False;
AddLog('*','PoP-List: Generating FileList');
IF (Cfg.ListFiles.DoBefore<>'') THEN RunCmd(Cfg.Listfiles.DoBefore,StartPath);
IF Cfg.ListFiles.DkDate THEN DatePicture:='dd-mm-yy' ELSE DatePicture:='mm-dd-yy';
New(Statistik);
New(AreaFreqLevel);
New(FilesBBS);
New(TopFiles);
New(Files);
New(Area);
FillChar(TopFiles^,SizeOf(TopFilesRec)*TopMax,0);
FillChar(Statistik^,SizeOf(StatistikRec)*Maxareas,0);
AreaNum:=ReadFileAreas(Area);
IF Cfg.AreaMan.AddInbound THEN DEC(AreaNum,3);
IF Cfg.ListFiles.OkBimodemPath <> '' THEN
BEGIN
New(F_OKBim, Init(Cfg.ListFiles.OkBimodemPath, SCreate, 1024));
IF F_OKBim=NIL THEN AddLog('!','Error writing BiModem OK-file - Ignoring!');
END ELSE
F_OKBim:=NIL;
CheckPortalOkFile;
IF MaxAvail>128000 THEN BufSiz:=Max64k((MaxAvail-128000) DIV 2) ELSE BufSiz:=1024;
New(F_List, Init(Cfg.ListFiles.FileList, SCreate, BufSiz));
DoDupeCheck:=Cfg.ListFiles.DupeCheck;
IF DodupeCheck AND (Maxavail<65535) THEN
BEGIN
AddLog('!','Not enough memory for DupeCheck - Ignoring!');
DoDupeCheck:=False;
END;
IF DoDupeCheck THEN
Dupes.Init(MaxDupes, 1, SizeOf(TDupeRec), '$DUPES.SRT', (MaxAvail-2048) DIV 3, lDeleteFile, DefaultPriority);
IF (IOResult=0) AND (Cfg.ListFiles.FileList<>'') THEN
BEGIN
IF (Cfg.ListFiles.Header<>'') AND ExistFile(Cfg.ListFiles.Header) THEN
BEGIN
Assign(F_File,Cfg.ListFiles.Header);FileMode:=ShareRead+ShareDenyNone;
Reset(F_File,1);
IF IOResult=0 THEN
BEGIN
StatStart:=FileSize(F_File)+4;
Close(F_File);
END;
New(F_Tmp, Init(Cfg.ListFiles.Header, SOpenRead+ShareDenyW, Max64k(MaxAvail-1024)));
IF F_Tmp<>NIL THEN
BEGIN
AddFile(F_Tmp,F_List);
Dispose(F_Tmp, Done);
END;
F_List^.WriteLn('');
F_List^.WriteLn('');
END ELSE
StatStart:=0;
IF Cfg.ListFiles.Stat THEN
BEGIN
FOR i:= 1 TO AreaNum+6 DO
F_List^.WriteLn(CharStr(' ',79));
TopStart:=StatStart+(AreaNum+6)*81
END Else
TopStart:=StatStart;
IF (Cfg.ListFiles.top<>0) AND Cfg.ListFiles.IncludeTop THEN
FOR i:= 1 TO Cfg.ListFiles.Top+3 DO F_List^.WriteLn(Pad('',79));
IF Cfg.ListFiles.NewsDays <> 0 THEN
BEGIN
New(F_News, Init(Cfg.ListFiles.NewsList, SCreate, BufSiz));
IF F_News=NIL THEN
BEGIN
AddLog('!','Error writing News-List - Ignoring!');
END Else
BEGIN
F_News^.WriteLn(' New files from the past '+Long2Str(Cfg.ListFiles.NewsDays)+' days.');
F_News^.WriteLn('');
END;
END ELSE
F_News:=NIL;
FOR i:=1 TO AreaNum DO
BEGIN
IF IncludeArea(Area^[i]^.Tag^) THEN
BEGIN
UpdateScreen;
ProcessFilesBBS(i);
IF F_OkBim<>NIL THEN F_OkBim^.WriteLn(Area^[i]^.Path^);
IF GotEsc THEN
BEGIN
AddLog('!','PoP-List: Generation aborted by user, using His/Her/Its own hands');
ViHarSnydt:=True;
GOTO SnydeFidus;
END;
END;
END;
SnydeFidus:
Arrow(6);
FooterStartPos:=F_LIST^.GetPos;
IF Cfg.ListFiles.Footer<>'' THEN
BEGIN
New(F_Tmp, Init(Cfg.ListFiles.Footer, SOpenRead+ShareDenyW, Max64k(MaxAvail-1024)));
IF F_Tmp<>NIL THEN
BEGIN
AddFile(F_Tmp,F_List);
Dispose(F_Tmp, Done);
END;
F_List^.WriteLn('');
F_List^.WriteLn('');
END;
PopFooter(F_List, NOT Cfg.ListFiles.Stat);
IF Cfg.ListFiles.NewsDays<>0 THEN PopFooter(F_News,False);
Dispose(F_List, Done);
IF F_News<>NIL THEN Dispose(F_News, Done);
IF (Cfg.ListFiles.StatFile <>'') OR Cfg.ListFiles.Stat THEN
InsertStat(Cfg.ListFiles.FileList,StatStart);
IF Cfg.ListFiles.IncludeTop AND (Cfg.ListFiles.Top <> 0) THEN InsertTop(Cfg.ListFiles.FileList,TopStart);
IF (Cfg.ListFiles.Top <> 0) AND (Cfg.ListFiles.TopFile <> '') THEN WriteTop;
END ELSE
BEGIN
AddLog('!','Error writing FileList - Aborting!');
ViHarSnydt:=True;
END;
Arrow(5);
IF DoDupeCheck THEN
BEGIN
IF NOT ViHarSnydt THEN CheckDupeFile;
Dupes.Done;
END;
{--}MakeSegments;
{$IFDEF MSGOBJECT}
PostStatMsg;
{$ENDIF}
DisposeFileAreas(Area,AreaNum);
Dispose(Area);
Dispose(Files);
Dispose(TopFiles);
Dispose(FilesBBS);
Dispose(Statistik);
Dispose(AreaFreqLevel);
IF F_OkBim<>NIL THEN Dispose(F_OkBim, Done);
IF NOT ViHarSnydt THEN
BEGIN
IF Cfg.ListFiles.DoPack<>'' THEN RunCmd(Cfg.Listfiles.DoPack,JustPathname(Cfg.ListFiles.FileList));
IF Cfg.ListFiles.DoAfter<>'' THEN RunCmd(Cfg.Listfiles.DoAfter,StartPath);
AddLog('*','PoP-List: Generation complete');
END;
Arrow(0);
ShowScreen(False);
InitialiseNodelist(cfg.NodeList,cfg.nodelisttyp);
{$ELSE}
AddLog('!','Not implemented in Portal of Power/Lite');
{$ENDIF}
END;
END.